﻿#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<functional>
#include<string>




int main()
{
	
	std::vector<std::string>everyIgnoreIp{

		//IPV4
		"1","1.1","1.1.1","1","1.1","1.1.1","1.2.3.4","1.a.1.1","126.1.1.1","256.1.1.1","1a.2.3.4",
		"1.1.1.1/0","-1.0.0.1","1.1.1.1/33","1.1.1.1/32","1.1.1.1/3a","1.1.1.1/a3","1111.1.1.1","1.1.111.1",
		//IPV6
		"0:0:0:0.1.1.1.1",
		
		"0:0:0:0:0:0:0:0","0:0:0:0:0:0:0:0:","0:0:0:0:0:0:0:0:0","abcd:ABCF:1:1:1:0:0:0","1:2:3:4:5:6:7","1:1:1:3:4:25678:1:1",
		"0:0:0:0:0:0:0:0g","0:0:0:0:0:0:0:0/1",
		"0:0:0:0:0:0:0:0/-1",
		"0:0:0:0:0:0:0:0/128",
		"0:0:0:0:0:0:0:0/128a",
		"0:0:0:0:0:0:0:0/129",
		"0:0:0:0:0:0:0:0/1a29",
		"::","::/1","::/","1::2","1::2:3:4","1::2:3:4:5:6:7:8",
		"1::2:3:4:5:6:7/1","1::2:3:4:5:6:7/0","1::2:3:4:5:6:7/128","1::2:3:4:5:6:7/129","1::2:3:4:5:6:7/a29",
		"1::2:3:4:5:6:7/2a9","::1:2:3/111","::1:2:3/0","::1:2:3/128","::1:2:3/129","::1:2:3/-1"

		
	
	};

	std::vector<std::string>::const_iterator vecBegin;
	std::string::const_iterator ipBegin, ipEnd, checkBegin,checkEnd;
	int ipv6MixLen{ 2 }, ipv6MaxLen{ 43 }, ipv4NumMaxLen{3}, ipv6NumMaxLen{4};

	bool doubleColon;
	bool isDoubleColon;
	bool isIpv4;
	char lastChar{};

	float f3, f2{10.0f};
	int sum,j;

	
	for (vecBegin = everyIgnoreIp.cbegin(); vecBegin != everyIgnoreIp.cend(); ++vecBegin)
	{
		doubleColon = isDoubleColon = false;
		ipBegin = vecBegin->cbegin(), ipEnd = vecBegin->cend();

		if (std::distance(ipBegin, ipEnd) < ipv6MixLen || std::distance(ipBegin, ipEnd) > ipv6MaxLen)
			goto invaildIp;



		checkBegin = std::find_if(ipBegin, ipEnd, [](const char ch)
		{
			return ((ch >= '0' && ch <= '9')
				|| (ch >= 'a' && ch <= 'f')
				|| (ch >= 'A' && ch <= 'F')
				|| ch == ':');
		});
		if (checkBegin != ipBegin)
			goto invaildIp;

		if (*checkBegin == ':')
		{
			if (*(checkBegin + 1) != ':')
				goto invaildIp;
			else
			{
				doubleColon = true;
				isDoubleColon = true;
				isIpv4 = false;
				checkBegin += 2;
				ipBegin = checkBegin;
			}
		}

		if (!doubleColon)
		{

			checkEnd = std::find_if_not(checkBegin + 1, ipEnd, [](const char ch)
			{
				return ((ch >= '0' && ch <= '9')
					|| (ch >= 'a' && ch <= 'f')
					|| (ch >= 'A' && ch <= 'F'));
			});

			if (checkEnd == ipEnd)
				goto invaildIp;

			if (*checkEnd != '.' && *checkEnd != ':')
				goto invaildIp;

			if (*checkEnd == '.')
				isIpv4 = true;
			else
				isIpv4 = false;

			if (isIpv4 && (std::distance(checkBegin, checkEnd) > ipv4NumMaxLen ||
				std::any_of(checkBegin, checkEnd,
					std::bind(std::logical_not<bool>(),
						std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9'))))))
				goto invaildIp;
			else if (!isIpv4 && std::distance(checkBegin, checkEnd) > ipv6NumMaxLen)
				goto invaildIp;


			if (isIpv4)
			{
				f3 = 0.1f;
				sum = std::accumulate(std::make_reverse_iterator(checkEnd),
					std::make_reverse_iterator(checkBegin), 0,
					[&f3, f2](int sum, int everyChar)
				{
					f3 *= f2;
					return sum += (everyChar - '0') * (static_cast<int>(f3));
				});

				if ((sum < 0 || sum > 255))
					goto invaildIp;
			}

			ipBegin = checkEnd;
			if (ipBegin != ipEnd)
				++ipBegin;
		}

		//IPV4地址判断分支
		if (isIpv4)
		{
			for (j = 1; j != 5; ++j)
			{
				checkBegin = std::find_if(ipBegin, ipEnd,
					std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

				if (checkBegin != ipBegin)
					goto invaildIp;

				checkEnd = std::find_if_not(checkBegin + 1, ipEnd,
					std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

				if (std::distance(checkBegin, checkEnd) > ipv4NumMaxLen)
					goto invaildIp;

				if (j < 3 && (checkEnd == ipEnd || *checkEnd != '.'))
					goto invaildIp;
				else if (j == 3 && (checkEnd != ipEnd && *checkEnd != '/'))
					goto invaildIp;
				else if (j == 4 && checkEnd != ipEnd)
					goto invaildIp;


				f3 = 0.1f;
				sum = std::accumulate(std::make_reverse_iterator(checkEnd),
					std::make_reverse_iterator(checkBegin), 0,
					[&f3, f2](int sum, int everyChar)
				{
					f3 *= f2;
					return sum += (everyChar - '0') * (static_cast<int>(f3));
				});

				if (j < 4 && (sum < 0 || sum > 255))
					goto invaildIp;
				else if (j == 4 && (sum < 0 || sum > 32))
					goto invaildIp;
				else if (j > 2 && checkEnd == ipEnd)
					break;


				ipBegin = checkEnd;
				if (*checkEnd == '/' && checkEnd + 1 == ipEnd)
					goto invaildIp;
				if (ipBegin != ipEnd)
					++ipBegin;

				if (j > 2 && ipBegin == ipEnd)
					break;
				else if (j == 4 && ipBegin != ipEnd)
					goto invaildIp;
			}
		}
		else    //IPV6地址判断分支
		{
			//bug
			lastChar = 0;
			for (j = 1; j != 9; ++j)
			{
				if (j < 8)
				{
					if (isDoubleColon && (ipBegin == ipEnd))
						break;



					if (ipBegin != ipEnd && *ipBegin == ':')
					{
						if (doubleColon)
							goto invaildIp;
						else
						{
							doubleColon = true;
							isDoubleColon = true;
							checkBegin = ipBegin + 1;
							ipBegin = checkBegin;
							continue;
						}
					}


					if (isDoubleColon && ipBegin == ipEnd)
						break;

					if (*ipBegin == '/' && ipBegin + 1 == ipEnd)
						goto invaildIp;

					if (*ipBegin != '/')
					{
						if (lastChar != '/')
						{
							checkBegin = std::find_if(ipBegin, ipEnd, [](const char ch)
							{
								return ((ch >= '0' && ch <= '9')
									|| (ch >= 'a' && ch <= 'f')
									|| (ch >= 'A' && ch <= 'F'));
							});


							if (checkBegin != ipBegin)
								goto invaildIp;

							checkEnd = std::find_if_not(checkBegin + 1, ipEnd, [](const char ch)
							{
								return ((ch >= '0' && ch <= '9')
									|| (ch >= 'a' && ch <= 'f')
									|| (ch >= 'A' && ch <= 'F'));
							});

							if (std::distance(checkBegin, checkEnd) > ipv6NumMaxLen)
								goto invaildIp;
						}
						else
						{
							checkBegin = std::find_if(ipBegin, ipEnd,
								std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));


							if (checkBegin != ipBegin)
								goto invaildIp;

							checkEnd = std::find_if_not(checkBegin + 1, ipEnd,
								std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

							if (std::distance(checkBegin, checkEnd) > 3 || checkEnd != ipEnd)
								goto invaildIp;

							f3 = 0.1f;
							sum = std::accumulate(std::make_reverse_iterator(checkEnd),
								std::make_reverse_iterator(checkBegin), 0,
								[&f3, f2](int sum, int everyChar)
							{
								f3 *= f2;
								return sum += (everyChar - '0') * (static_cast<int>(f3));
							});

							if ((sum < 0 || sum > 128))
								goto invaildIp;
							break;

						}
					}
					else
					{
						checkBegin = std::find_if(ipBegin + 1, ipEnd,
							std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));


						if (checkBegin != ipBegin + 1)
							goto invaildIp;

						checkEnd = std::find_if_not(checkBegin + 1, ipEnd,
							std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));


						if (std::distance(checkBegin, checkEnd) > ipv6NumMaxLen || checkEnd != ipEnd)
							goto invaildIp;

					}

					if (lastChar == '/')
					{
						f3 = 0.1f;
						sum = std::accumulate(std::make_reverse_iterator(checkEnd),
							std::make_reverse_iterator(checkBegin), 0,
							[&f3, f2](int sum, int everyChar)
						{
							f3 *= f2;
							return sum += (everyChar - '0') * (static_cast<int>(f3));
						});

						if ((sum < 0 || sum > 128))
							goto invaildIp;
					}

					if (checkEnd != ipEnd)
						lastChar = *checkEnd;

				}
				else
				{
					checkBegin = std::find_if(ipBegin, ipEnd,
						std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

					if (checkBegin != ipBegin)
						goto invaildIp;

					checkEnd = std::find_if_not(checkBegin + 1, ipEnd,
						std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

					if (std::distance(checkBegin, checkEnd) > ipv6NumMaxLen - 1)
						goto invaildIp;

					
					if(checkEnd!= ipEnd)
						goto invaildIp;
					
					f3 = 0.1f;
					sum = std::accumulate(std::make_reverse_iterator(checkEnd),
						std::make_reverse_iterator(checkBegin), 0,
						[&f3, f2](int sum, int everyChar)
					{
						f3 *= f2;
						return sum += (everyChar - '0') * (static_cast<int>(f3));
					});

					if ((sum < 0 || sum > 128))
						goto invaildIp;
					break;
						
					//bug
				}

				if (doubleColon && checkEnd == ipEnd)
				{
					if (lastChar == '/')
					{
						f3 = 0.1f;
						sum = std::accumulate(std::make_reverse_iterator(checkEnd),
							std::make_reverse_iterator(checkBegin), 0,
							[&f3, f2](int sum, int everyChar)
						{
							f3 *= f2;
							return sum += (everyChar - '0') * (static_cast<int>(f3));
						});

						if ((sum < 0 || sum > 128))
							goto invaildIp;
					}
					else if (*ipBegin == '/')
					{
						checkBegin = std::find_if(ipBegin + 1, ipEnd,
							std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

						if (checkBegin != ipBegin + 1)
							goto invaildIp;

						checkEnd = std::find_if_not(checkBegin + 1, ipEnd,
							std::bind(std::logical_and<bool>(), std::bind(std::greater_equal<char>(), std::placeholders::_1, '0'), std::bind(std::less_equal<char>(), std::placeholders::_1, '9')));

						if (std::distance(checkBegin, checkEnd) > 3)
							goto invaildIp;

						f3 = 0.1f;
						sum = std::accumulate(std::make_reverse_iterator(checkEnd),
							std::make_reverse_iterator(checkBegin), 0,
							[&f3, f2](int sum, int everyChar)
						{
							f3 *= f2;
							return sum += (everyChar - '0') * (static_cast<int>(f3));
						});

						if ((sum < 0 || sum > 128))
							goto invaildIp;
					}
					break;
				}
				else if (!doubleColon &&  j < 7 && (checkEnd == ipEnd || *checkEnd != ':'))
					goto invaildIp;
				else if (j == 7 && (checkEnd != ipEnd && *checkEnd != '/'))
					goto invaildIp;
				else if (j > 6 && checkEnd == ipEnd)
					break;

				if (j == 8)
				{
					f3 = 0.1f;
					sum = std::accumulate(std::make_reverse_iterator(checkEnd),
						std::make_reverse_iterator(checkBegin), 0,
						[&f3, f2](int sum, int everyChar)
					{
						f3 *= f2;
						return sum += (everyChar - '0') * (static_cast<int>(f3));
					});

					if ((sum < 0 || sum > 128))
						goto invaildIp;
				}

				ipBegin = checkEnd;
				if (*checkEnd == '/' && checkEnd + 1 == ipEnd)
					goto invaildIp;
				if (ipBegin != ipEnd)
					++ipBegin;

				if (j > 6 && ipBegin == ipEnd)
					break;
				else if (j == 8 && ipBegin != ipEnd)
					goto invaildIp;

				isDoubleColon = false;
			}
		}
		std::cout << std::string(vecBegin->cbegin(), vecBegin->cend()) << "     true\n";
		continue;

	invaildIp:
		std::cout << std::string(vecBegin->cbegin(), vecBegin->cend()) << "     false\n";
	}


	return 0;
}